package com.talent.proxy.mysql.common.packets.s2c.resultset;

import java.nio.ByteBuffer;

import com.talent.aio.common.ChannelContext;
import com.talent.proxy.mysql.common.MysqlExt;
import com.talent.proxy.mysql.common.MysqlPacket;
import com.talent.proxy.mysql.common.MysqlReturn;
import com.talent.proxy.mysql.common.utils.BufferUtil;

/**
 * 
 * <pre>
 	lenenc_str     catalog
	lenenc_str     schema
	lenenc_str     table
	lenenc_str     org_table
	lenenc_str     name
	lenenc_str     org_name
	lenenc_int     length of fixed-length fields [0c]
	2              character set
	4              column length
	1              type
	2              flags
	1              decimals
	2              filler [00] [00]
	  if command was COM_FIELD_LIST {
	lenenc_int     length of default-values
	string[$len]   default values
	  }
	</pre>
 * @see http://dev.mysql.com/doc/internals/en/com-query-response.html#column-definition
 */
public class FieldMetaDataPacket extends MysqlPacket
{
	private static final byte[] DEFAULT_CATALOG = "def".getBytes();
	private static final byte NEXT_LENGTH = 0x0c;
	private static final byte[] FILLER = { 00, 00 };

	public byte[] catalog = DEFAULT_CATALOG;// always "def"
	public String catalogStr;
	public byte[] schema;
	public String schemaStr;
	public byte[] table;
	public String tableStr;
	public byte[] orgTable;
	public String orgTableStr;
	public byte[] name;
	public String nameStr;
	public byte[] orgName;
	public String orgNameStr;
	public byte nextLength = NEXT_LENGTH;// always 0x0c
	public int charsetSet;
	public long columnLength; //maximum length of the field
	/**
	 * @see com.talent.proxy.mysql.common.MysqlColumnType
	 */
	public int columnType;
	public int flags;
	/**
	 * max shown decimal digits(最大显示小数位数)
	 * <div class="itemizedlist"><ul class="itemizedlist" type="circle">
	<li class="listitem"><p>
	                              <code class="literal">0x00</code> for integers
	                              and static strings
	                            </p></li>
	<li class="listitem"><p>
	                              <code class="literal">0x1f</code> for dynamic
	                              strings, double, float
	                            </p></li>
	<li class="listitem"><p>
	                              <code class="literal">0x00</code> to
	                              <code class="literal">0x51</code> for decimals
	                            </p></li>
	</ul></div>
	 */
	public byte decimals;
	public byte[] filler = FILLER;
	public byte[] defaultValues;
	public String defaultValuesStr;

	public boolean isCompletePacket()
	{
		return false;
	}

	public void decodeBody(ByteBuffer buffer, ChannelContext<MysqlExt, MysqlPacket, MysqlReturn> channelContext)
	{

		int initposition = buffer.position();

		this.catalog = BufferUtil.readBytesWithLength(buffer);
		catalogStr = new String(catalog);
		this.schema = BufferUtil.readBytesWithLength(buffer);
		schemaStr = new String(schema);

		this.table = BufferUtil.readBytesWithLength(buffer);
		tableStr = new String(table);
		this.orgTable = BufferUtil.readBytesWithLength(buffer);
		orgTableStr = new String(orgTable);
		this.name = BufferUtil.readBytesWithLength(buffer);
		nameStr = new String(name);
		this.orgName = BufferUtil.readBytesWithLength(buffer);
		orgNameStr = new String(orgName);
		this.nextLength = BufferUtil.read(buffer);
		this.charsetSet = BufferUtil.readUB2(buffer);
		this.columnLength = BufferUtil.readUB4(buffer);
		this.columnType = BufferUtil.read(buffer) & 0xff;
		this.flags = BufferUtil.readUB2(buffer);
		this.decimals = BufferUtil.read(buffer);
		this.filler = BufferUtil.readBytes(buffer, 2);

		int usedlength = buffer.position() - initposition;
		if (usedlength < bodySize)
		{
			defaultValues = BufferUtil.readBytesWithLength(buffer);
			defaultValuesStr = new String(defaultValues);
		}
	}

	@Override
	public ByteBuffer encode(ChannelContext<MysqlExt, MysqlPacket, MysqlReturn> channelContext)
	{
		int bodySize = bodySize();
		ByteBuffer buffer = ByteBuffer.allocate(HEADER_SIZE + bodySize);
		BufferUtil.writeUB3(buffer, bodySize);
		buffer.put(seqId);
		BufferUtil.writeWithLength(buffer, catalog, (byte) 0);
		BufferUtil.writeWithLength(buffer, schema, (byte) 0);
		BufferUtil.writeWithLength(buffer, table, (byte) 0);
		BufferUtil.writeWithLength(buffer, orgTable, (byte) 0);
		BufferUtil.writeWithLength(buffer, name, (byte) 0);
		BufferUtil.writeWithLength(buffer, orgName, (byte) 0);
		buffer.put(NEXT_LENGTH);
		BufferUtil.writeUB2(buffer, charsetSet);
		BufferUtil.writeUB4(buffer, columnLength);
		buffer.put((byte) (columnType & 0xff));
		BufferUtil.writeUB2(buffer, flags);
		buffer.put(decimals);
		buffer.put(FILLER);
		if (defaultValues != null)
		{
			//only use for show columns
			BufferUtil.writeWithLength(buffer, defaultValues);
		}
		return buffer;
	}

	@Override
	public int bodySize()
	{
		int size = (catalog == null ? 1 : BufferUtil.getLength(catalog));
		size += (schema == null ? 1 : BufferUtil.getLength(schema));
		size += (table == null ? 1 : BufferUtil.getLength(table));
		size += (orgTable == null ? 1 : BufferUtil.getLength(orgTable));
		size += (name == null ? 1 : BufferUtil.getLength(name));
		size += (orgName == null ? 1 : BufferUtil.getLength(orgName));
		size += 13;
		if (defaultValues != null)
		{
			size += BufferUtil.getLength(defaultValues);
		}
		return size;
	}

	@Override
	protected String packetDesc()
	{
		return "MySQL Column Definition Packet";
	}

	/** 
	 * @see com.talent.proxy.mysql.common.MysqlPacket#onReceived(com.talent.aio.common.ChannelContext)
	 * 
	 * @param channelContext
	 * @return
	 * @重写人: tanyaowu
	 * @重写时间: 2017年1月23日 下午4:59:30
	 * 
	 */
	@Override
	public MysqlReturn onReceived(ChannelContext<MysqlExt, MysqlPacket, MysqlReturn> channelContext)
	{
		// TODO Auto-generated method stub
		return null;
	}

}
